package com.dreamlin.app.widget

import android.animation.Animator
import android.animation.ObjectAnimator
import android.animation.ValueAnimator
import android.animation.ValueAnimator.AnimatorUpdateListener
import android.content.Context
import android.graphics.PixelFormat
import android.graphics.Region
import android.util.AttributeSet
import android.view.DragEvent
import android.view.Gravity
import android.view.View
import android.view.View.OnDragListener
import android.view.WindowManager
import androidx.appcompat.widget.AppCompatImageView
import androidx.core.view.ViewCompat
import com.dreamlin.app.common.dp2px
import com.dreamlin.app.common.getScreenHeight
import com.dreamlin.app.common.getScreenWidth

class FloatingBall @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) :
    AppCompatImageView(context, attrs, defStyleAttr), OnDragListener,
    Animator.AnimatorListener,
    AnimatorUpdateListener {
    private lateinit var mFloatBallParams: WindowManager.LayoutParams
    private lateinit var mWindowManager: WindowManager
    private val mScreenHeight: Int
    private val mScreenWidth: Int
    private var viewAnimator: ObjectAnimator? = null

    init {
        initFloatBallParams(context)
        setOnDragListener(this)
        setOnLongClickListener { v ->
            ViewCompat.startDragAndDrop(v, null, DragShadowBuilder(v), v, 0)
            false
        }
        mScreenWidth = getScreenWidth()
        mScreenHeight = getScreenHeight()
    }

    fun setCurrentX(currentX: Float) {
        floatX = currentX
        update()
    }

    private fun getAnimator(curX: Float, targetX: Float): ObjectAnimator {
        if (viewAnimator == null) {
            viewAnimator = ObjectAnimator.ofFloat(
                this, "currentX",
                curX, targetX
            )
            viewAnimator?.addUpdateListener(this)
            viewAnimator?.addListener(this)
            viewAnimator?.duration = 800
        } else {
            viewAnimator?.setFloatValues(curX, targetX)
        }

        return viewAnimator!!
    }

    /**
     * 获取悬浮球的布局参数
     */
    private fun initFloatBallParams(context: Context) {
        mFloatBallParams = WindowManager.LayoutParams()
        mFloatBallParams.flags = (mFloatBallParams.flags
                or WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
                or WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                or WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE)
        mFloatBallParams.dimAmount = 0.2f
        //      mFloatBallParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
        mFloatBallParams.height = WindowManager.LayoutParams.WRAP_CONTENT
        mFloatBallParams.width = WindowManager.LayoutParams.WRAP_CONTENT
        mFloatBallParams.gravity = Gravity.START or Gravity.TOP
        mFloatBallParams.format = PixelFormat.RGBA_8888
        // 设置整个窗口的透明度
        mFloatBallParams.alpha = 1.0f
        // 显示悬浮球在屏幕左上角
        mFloatBallParams.x = 0
        mFloatBallParams.y = 0
        mWindowManager =
            context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
    }


    /**
     * 显示悬浮
     */
    fun showFloat() {
        /*if (!inScreen(FloatingButton.floatX.toInt(), FloatingButton.floatY.toInt())) {
            //read last position
            val floatDataX = getFloatData(TRANSITION_X)
            val floatDataY = getFloatData(TRANSITION_Y)
            if (!inScreen(floatDataX.toInt(), floatDataY.toInt())) {
                //init x, y

            }
            floatX = mScreenWidth - 18f.dp2px() - 75f.dp2px()
            floatY = mScreenHeight - 15f.dp2px() - 75f.dp2px()
        }*/
        floatX = mScreenWidth - 18f.dp2px() - 75f.dp2px()
        floatY = mScreenHeight - 15f.dp2px() - 75f.dp2px()
        mFloatBallParams.x = floatX.toInt()
        mFloatBallParams.y = floatY.toInt()
        measure(
            MeasureSpec.makeMeasureSpec(75f.dp2px().toInt(), MeasureSpec.EXACTLY),
            MeasureSpec.makeMeasureSpec(75f.dp2px().toInt(), MeasureSpec.EXACTLY)
        )
        try {
            mWindowManager.addView(this, mFloatBallParams)
        } catch (ex: IllegalStateException) {
            ex.printStackTrace()
        }
    }

    private fun update() {
        mFloatBallParams.x = floatX.toInt()
        mFloatBallParams.y = floatY.toInt()
        mWindowManager.updateViewLayout(this, mFloatBallParams)
    }

    /**
     * 移除该view
     */
    fun dismissFloatView() {
        mWindowManager.removeViewImmediate(this)

    }

    private fun inScreen(x: Int, y: Int): Boolean {
        val region = Region(0, 0, mScreenWidth - width, mScreenHeight - height)
        return region.contains(x, y)
    }

    private fun isLeft(): Boolean {
        val center = getScreenWidth() / 2
        return floatX <= center
    }

    override fun onDrag(
        v: View,
        event: DragEvent
    ): Boolean {
        if (v === this) when (event.action) {
            DragEvent.ACTION_DRAG_STARTED -> visibility = View.INVISIBLE
            DragEvent.ACTION_DRAG_ENDED -> {
//                floatX = event.x
//                floatY = event.y
//                update()
                visibility = View.VISIBLE
//                if (isLeft()) {
//                    getAnimator(floatX, 18f.dp2px()).start()
//                } else {
//                    getAnimator(floatX, mScreenWidth - 18f.dp2px() - width).start()
//                }
            }

            DragEvent.ACTION_DROP -> {
                floatX = event.x
                floatY = event.y
            }
        }
        return true
    }

    override fun onAnimationStart(animation: Animator) {}

    override fun onAnimationEnd(animation: Animator) {
        update()
    }

    override fun onAnimationCancel(animation: Animator) {}
    override fun onAnimationRepeat(animation: Animator) {}
    override fun onAnimationUpdate(animation: ValueAnimator) {
        update()
    }

    companion object {
        private const val TAG = "FloatingView"
        private var floatX = -1f
        private var floatY = -1f
    }

}